package com.zhoug.zmui3.date;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.TextView;

import com.zhoug.common3.utils.LogUtils;
import com.zhoug.common3.utils.TimeUtils;
import com.zhoug.zmui3.R;
import com.zhoug.zmui3.ZMUINumberPicker;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

/**
 * 日期控件
 *
 * @Author 35574
 * @Date 2021/4/12
 * @Description
 */
public class ZMUIDatePicker extends LinearLayout implements DateSelectInterface, NumberPicker.OnValueChangeListener {
    private static final String TAG = ">>>ZMUIDatePicker";
    private static final boolean DEBUG = false;
    public static final int MODE_DATE = DateSelectInterface.MODE_DATE;//0001 年月日
    public static final int MODE_TIME = DateSelectInterface.MODE_TIME;//0010 时分
    public static final int MODE_DATE_TIME = DateSelectInterface.MODE_DATE_TIME;//年月日 时分
    /**
     * 选择模式:日期还是时间
     * {@link  #MODE_DATE,#MODE_TIME,#MODE_DATE_TIME}
     */
    private int mMode = MODE_DATE;
    public static final int HORIZONTAL = DateSelectInterface.HORIZONTAL;//水平对齐
    public static final int VERTICAL = DateSelectInterface.VERTICAL;//垂直对齐
    /**
     * 对齐方式
     */
    private int mOrientation = HORIZONTAL;
    /**
     * 选择的值
     */
    private int mSelectYear;//年
    private int mSelectMonth;//月
    private int mSelectDay;//日
    private int mSelectHour;//时
    private int mSelectMinute;//分

    private ZMUINumberPicker mNumberPickerYear;//年
    private ZMUINumberPicker mNumberPickerMonth;//月
    private ZMUINumberPicker mNumberPickerDay;//日
    private ZMUINumberPicker mNumberPickerHour;//时
    private ZMUINumberPicker mNumberPickerMinute;//分
    private ViewGroup mContainerDate;//
    private ViewGroup mContainerTime;//

    private TextView mTvYearSuffix;
    private TextView mTvMonthSuffix;
    private TextView mTvDaySuffix;
    private TextView mTvHourSuffix;
    private TextView mTvMinuteSuffix;

    private boolean mShowYear = true;
    private boolean mShowMonth = true;
    private boolean mShowDay = true;
    private boolean mShowHour = true;
    private boolean mShowMinute = true;

    private static final int DEF_MIN_YEAR = 1900;
    private static final int DEF_MAX_YEAR = 2200;

    /**
     * 允许选择的最大值和最小值
     */
    private int mMinYear = DEF_MIN_YEAR;//年的最小值
    private int mMaxYear = DEF_MAX_YEAR;//年的最大值
    private int mMinMonth = 1;
    private int mMaxMonth = 12;
    private int mMinDay = 1;
    private int mMaxDay = 31;
    private int mMinHour = 0;
    private int mMaxHour = 23;
    private int mMinMinute = 0;
    private int mMaxMinute = 59;

    /**
     * s日期数据格式
     */
    private static final String DATE_FORMAT = "yyyy-MM-dd";
    private static final String TIME_FORMAT = "HH:mm";
    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    private String mDateFormat;

    /**
     * 后缀
     */
    private String mYearSuffix = "年";
    private String mMonthSuffix = "月";
    private String mDaySuffix = "日";
    private String mHourSuffix = "时";
    private String mMinuteSuffix = "分";
    public static final int SUFFIX_POSITION_OUT = 1;//后缀在数据之外
    public static final int SUFFIX_POSITION_IN = 2;//后缀包含在数据中
    private int mSuffixPosition = SUFFIX_POSITION_IN;

    private OnSelectChangeListener onSelectChangeListener;
    private static Matcher MATCHER_NUMBER = Pattern.compile("\\d+").matcher("");


    public ZMUIDatePicker(@NonNull Context context) {
        this(context, null);
    }

    public ZMUIDatePicker(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, R.attr.zmui_style_ZMUIDatePicker);
    }

    public ZMUIDatePicker(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        parseAttrs(context, attrs, defStyleAttr);
        initView(context);
        initDate();
    }

    private void parseAttrs(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ZMUIDatePicker, defStyleAttr, 0);
        mMode = a.getInt(R.styleable.ZMUIDatePicker_zmui_date_mode, MODE_DATE);
        mOrientation = a.getInt(R.styleable.ZMUIDatePicker_zmui_dateTime_orientation, HORIZONTAL);
        if (DEBUG) {
            LogUtils.d(TAG, "parseAttrs:mMode=" + mMode);
        }
        a.recycle();
    }

    private void initView(Context context) {
        if (DEBUG) {
            LogUtils.d(TAG, "initView:");
        }
        View root;
        if (mOrientation == HORIZONTAL) {
            root = LayoutInflater.from(context).inflate(R.layout.zmui_date_time_picker_horizontal, this, false);
        } else {
            root = LayoutInflater.from(context).inflate(R.layout.zmui_date_time_picker_vertical, this, false);
        }
        addView(root);


        //初始化View
        mNumberPickerYear = findViewById(R.id.date_numberPicker_year);
        mNumberPickerMonth = findViewById(R.id.date_numberPicker_month);
        mNumberPickerDay = findViewById(R.id.date_numberPicker_day);
        mNumberPickerHour = findViewById(R.id.date_numberPicker_hour);
        mNumberPickerMinute = findViewById(R.id.date_numberPicker_minute);
        mContainerDate = findViewById(R.id.container_date);
        mContainerTime = findViewById(R.id.container_time);
        mTvYearSuffix = findViewById(R.id.date_tv_year);
        mTvMonthSuffix = findViewById(R.id.date_tv_month);
        mTvDaySuffix = findViewById(R.id.date_tv_day);
        mTvHourSuffix = findViewById(R.id.date_tv_hour);
        mTvMinuteSuffix = findViewById(R.id.date_tv_minute);


        mNumberPickerYear.setOnValueChangedListener(this);
        mNumberPickerMonth.setOnValueChangedListener(this);
        mNumberPickerDay.setOnValueChangedListener(this);
        mNumberPickerHour.setOnValueChangedListener(this);
        mNumberPickerMinute.setOnValueChangedListener(this);
        //默认选中的日期为今天
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(System.currentTimeMillis());
        mSelectYear = c.get(Calendar.YEAR);
        mSelectMonth = c.get(Calendar.MONTH) + 1;
        mSelectDay = c.get(Calendar.DAY_OF_MONTH);
        mSelectHour = c.get(Calendar.HOUR_OF_DAY);
        mSelectMinute = c.get(Calendar.MINUTE);

    }


    private boolean isShowDate() {
        return (mMode & MODE_DATE) == MODE_DATE;
    }

    private boolean isShowTime() {
        return (mMode & MODE_TIME) == MODE_TIME;
    }

    private void initDate() {
        if (DEBUG) {
            LogUtils.d(TAG, "initDate:");
        }
        mTvYearSuffix.setText(mYearSuffix);
        mTvMonthSuffix.setText(mMonthSuffix);
        mTvDaySuffix.setText(mDaySuffix);
        mTvHourSuffix.setText(mHourSuffix);
        mTvMinuteSuffix.setText(mMinuteSuffix);

        setDateVisibility(false);
        setTimeVisibility(false);
        //选择日期
        if (isShowDate()) {
            setDateVisibility(true);
            initYear();
            refreshMonthOnChange();
            refreshDayOnChange();
        }
        if (isShowTime()) {
            //选择时间
            setTimeVisibility(true);
            refreshHourOnChange();
            refreshMinuteOnChange();
        }
    }


    public void showYear(boolean show) {
        this.mShowYear = show;
        if (isShowDate()) {
            if (show) {
                mNumberPickerYear.setVisibility(VISIBLE);
                if (mSuffixPosition == SUFFIX_POSITION_IN) {
                    mTvYearSuffix.setVisibility(GONE);
                } else {
                    mTvYearSuffix.setVisibility(VISIBLE);
                }
            } else {
                mNumberPickerYear.setVisibility(GONE);
                mTvYearSuffix.setVisibility(GONE);
            }
        }
    }

    public void showMonth(boolean show) {
        this.mShowMonth = show;
        if (isShowDate()) {
            if (show) {
                mNumberPickerMonth.setVisibility(VISIBLE);
                if (mSuffixPosition == SUFFIX_POSITION_IN) {
                    mTvMonthSuffix.setVisibility(GONE);
                } else {
                    mTvMonthSuffix.setVisibility(VISIBLE);
                }
            } else {
                mNumberPickerMonth.setVisibility(GONE);
                mTvMonthSuffix.setVisibility(GONE);
            }
        }
    }

    public void showDay(boolean show) {
        this.mShowDay = show;
        if (isShowDate()) {
            if (show) {
                mNumberPickerDay.setVisibility(VISIBLE);
                if (mSuffixPosition == SUFFIX_POSITION_IN) {
                    mTvDaySuffix.setVisibility(GONE);
                } else {
                    mTvDaySuffix.setVisibility(VISIBLE);
                }
            } else {
                mNumberPickerDay.setVisibility(GONE);
                mTvDaySuffix.setVisibility(GONE);
            }
        }
    }

    public void showHour(boolean show) {
        this.mShowHour = show;
        if (isShowTime()) {
            if (show) {
                mNumberPickerHour.setVisibility(VISIBLE);
                if (mSuffixPosition == SUFFIX_POSITION_IN) {
                    mTvHourSuffix.setVisibility(GONE);
                } else {
                    mTvHourSuffix.setVisibility(VISIBLE);
                }
            } else {
                mNumberPickerHour.setVisibility(GONE);
                mTvHourSuffix.setVisibility(GONE);
            }
        }
    }

    public void showMinute(boolean show) {
        this.mShowMinute = show;
        if (isShowTime()) {
            if (show) {
                mNumberPickerMinute.setVisibility(VISIBLE);
                if (mSuffixPosition == SUFFIX_POSITION_IN) {
                    mTvMinuteSuffix.setVisibility(GONE);
                } else {
                    mTvMinuteSuffix.setVisibility(VISIBLE);
                }
            } else {
                mNumberPickerMinute.setVisibility(GONE);
                mTvMinuteSuffix.setVisibility(GONE);
            }
        }
    }


    private void setDateVisibility(boolean visibility) {
        if (visibility) {
            if (mContainerDate != null) {
                mContainerDate.setVisibility(VISIBLE);
            }
            mNumberPickerYear.setVisibility(VISIBLE);
            mNumberPickerMonth.setVisibility(VISIBLE);
            mNumberPickerDay.setVisibility(VISIBLE);
            if (mSuffixPosition == SUFFIX_POSITION_IN) {
                mTvYearSuffix.setVisibility(GONE);
                mTvMonthSuffix.setVisibility(GONE);
                mTvDaySuffix.setVisibility(GONE);
            } else {
                mTvYearSuffix.setVisibility(VISIBLE);
                mTvMonthSuffix.setVisibility(VISIBLE);
                mTvDaySuffix.setVisibility(VISIBLE);
            }
        } else {
            if (mContainerDate != null) {
                mContainerDate.setVisibility(GONE);
            }
            mNumberPickerYear.setVisibility(GONE);
            mNumberPickerMonth.setVisibility(GONE);
            mNumberPickerDay.setVisibility(GONE);
            mTvYearSuffix.setVisibility(GONE);
            mTvMonthSuffix.setVisibility(GONE);
            mTvDaySuffix.setVisibility(GONE);
        }

        showYear(mShowYear);
        showMonth(mShowMonth);
        showDay(mShowDay);
    }

    private void setTimeVisibility(boolean visibility) {
        if (visibility) {
            if (mContainerTime != null) {
                mContainerTime.setVisibility(VISIBLE);
            }
            mNumberPickerHour.setVisibility(VISIBLE);
            mNumberPickerMinute.setVisibility(VISIBLE);
            if (mSuffixPosition == SUFFIX_POSITION_IN) {
                mTvHourSuffix.setVisibility(GONE);
                mTvMinuteSuffix.setVisibility(GONE);
            } else {
                mTvHourSuffix.setVisibility(VISIBLE);
                mTvMinuteSuffix.setVisibility(VISIBLE);
            }
        } else {
            if (mContainerTime != null) {
                mContainerTime.setVisibility(GONE);
            }
            mNumberPickerHour.setVisibility(GONE);
            mNumberPickerMinute.setVisibility(GONE);
            mTvHourSuffix.setVisibility(GONE);
            mTvMinuteSuffix.setVisibility(GONE);
        }

        showHour(mShowHour);
        showMinute(mShowMinute);

    }

    /**
     * 初始化年选择器
     */
    private void initYear() {
        String suffix = mSuffixPosition == SUFFIX_POSITION_IN ? mYearSuffix : null;
        String[] displayYears = DateTimeUtils.getDisplayYears(mMinYear, mMaxYear, suffix);
        mNumberPickerYear.setDisplayedValues(null);
        mNumberPickerYear.setMinValue(0);
        mNumberPickerYear.setMaxValue(displayYears.length - 1);
        mNumberPickerYear.setDisplayedValues(displayYears);
        //设置选中的年
        mSelectYear = setSelect(mNumberPickerYear, mSelectYear);
        if (DEBUG) {
            LogUtils.d(TAG, "刷新集合:年");
        }
    }

    /**
     * 根据年的变化刷新月份数据
     */
    private void refreshMonthOnChange() {
        String suffix = mSuffixPosition == SUFFIX_POSITION_IN ? mMonthSuffix : null;
        String[] displayedValues = mNumberPickerMonth.getDisplayedValues();
        String[] displayMonths = null;
        if (displayedValues == null) {
            //第一次初始化月
            if (mMaxYear == mMinYear && mSelectYear == mMaxYear && mMaxMonth != 12 && mMinMonth > 0) {
                //最大年和最小年相等
                displayMonths = DateTimeUtils.getDisplayMonths(mMinMonth, mMaxMonth, suffix);
            } else if (mSelectYear == mMaxYear && mMaxMonth != 12) {
                //选中最大年,设置了最大月
                displayMonths = DateTimeUtils.getDisplayMonths(1, mMaxMonth, suffix);
            } else if (mSelectYear == mMinYear && mMinMonth > 0) {
                //选中最小年,设置最小月
                displayMonths = DateTimeUtils.getDisplayMonths(mMinMonth, 12, suffix);
            } else {
                displayMonths = DateTimeUtils.getDisplayMonths(1, 12, suffix);
            }
        } else {
            if (mSelectYear == mMaxYear && mMaxMonth != 12) {
                //选中最大年,设置了最大月
                displayMonths = DateTimeUtils.getDisplayMonths(1, mMaxMonth, suffix);
            } else if (mSelectYear == mMinYear && mMinMonth > 0) {
                //选中最小年,设置最小月
                displayMonths = DateTimeUtils.getDisplayMonths(mMinMonth, 12, suffix);
            } else if (displayedValues.length != 12) {
                displayMonths = DateTimeUtils.getDisplayMonths(1, 12, suffix);
            }
        }

        if (displayMonths != null) {
            mNumberPickerMonth.setDisplayedValues(null);
            mNumberPickerMonth.setMinValue(0);
            mNumberPickerMonth.setMaxValue(displayMonths.length - 1);
            mNumberPickerMonth.setDisplayedValues(displayMonths);
            if (DEBUG) {
                LogUtils.d(TAG, "刷新集合:月");
            }
        }
        mSelectMonth = setSelect(mNumberPickerMonth, mSelectMonth);
    }

    /**
     * 根据年月的变化刷新天数据
     */
    private void refreshDayOnChange() {
        String suffix = mSuffixPosition == SUFFIX_POSITION_IN ? mDaySuffix : null;
        String[] displayDays = null;
        if (mSelectYear == mMaxYear && mSelectMonth == mMaxMonth && mMaxDay > 0) {
            //最大天
            displayDays = DateTimeUtils.getDisplayDays(mSelectYear, mSelectMonth, 1, mMaxDay, suffix);
        } else if (mSelectYear == mMinYear && mSelectMonth == mMinMonth && mMinDay > 0) {
            //最小天
            displayDays = DateTimeUtils.getDisplayDays(mSelectYear, mSelectMonth, mMinDay, 0, suffix);
        } else {
            displayDays = DateTimeUtils.getDisplayDays(mSelectYear, mSelectMonth, 0, 0, suffix);
        }

        mNumberPickerDay.setDisplayedValues(null);//
        mNumberPickerDay.setMinValue(0);
        mNumberPickerDay.setMaxValue(displayDays.length - 1);
        mNumberPickerDay.setDisplayedValues(displayDays);
        mSelectDay = setSelect(mNumberPickerDay, mSelectDay);
        if (DEBUG) {
            LogUtils.d(TAG, "刷新集合:天");
        }

    }

    /**
     * 刷新时间集合
     */
    private void refreshHourOnChange() {
        String suffix = mSuffixPosition == SUFFIX_POSITION_IN ? mHourSuffix : null;

        String[] displayedValues = mNumberPickerHour.getDisplayedValues();
        String[] hours = null;

        if (displayedValues == null) {
            if (isShowDate()) {
                if (mSelectYear == mMaxYear && mSelectMonth == mMaxMonth && mSelectDay == mMaxDay && mMaxHour != 23) {
                    //设置最大时间
                    hours = DateTimeUtils.getDisplayHours(0, mMaxHour, suffix);
                } else if (mSelectYear == mMinYear && mSelectMonth == mMinMonth && mSelectDay == mMinDay && mMinHour != 0) {
                    //设置最小时间
                    hours = DateTimeUtils.getDisplayHours(mMinHour, 23, suffix);
                } else {
                    hours = DateTimeUtils.getDisplayHours(0, 23, suffix);
                }
            } else {
                hours = DateTimeUtils.getDisplayHours(mMinHour, mMaxHour, suffix);
            }
        } else {
            if (isShowDate()) {
                if (mSelectYear == mMaxYear && mSelectMonth == mMaxMonth && mSelectDay == mMaxDay && mMaxHour != 23) {
                    //设置最大时间
                    hours = DateTimeUtils.getDisplayHours(0, mMaxHour, suffix);
                } else if (mSelectYear == mMinYear && mSelectMonth == mMinMonth && mSelectDay == mMinDay && mMinHour != 0) {
                    //设置最小时间
                    hours = DateTimeUtils.getDisplayHours(mMinHour, 23, suffix);
                } else {
                    if (displayedValues.length != 24) {
                        hours = DateTimeUtils.getDisplayHours(0, 23, suffix);
                    }
                }
            } else {
                hours = DateTimeUtils.getDisplayHours(mMinHour, mMaxHour, suffix);
            }


        }
        if (hours != null) {
            if (DEBUG) {
                LogUtils.d(TAG, "刷新集合:时");
            }
            mNumberPickerHour.setDisplayedValues(null);//
            mNumberPickerHour.setMinValue(0);
            mNumberPickerHour.setMaxValue(hours.length - 1);
            mNumberPickerHour.setDisplayedValues(hours);
        }
        mSelectHour = setSelect(mNumberPickerHour, mSelectHour);

    }

    /**
     *
     */
    private void refreshMinuteOnChange() {
        String suffix = mSuffixPosition == SUFFIX_POSITION_IN ? mMinuteSuffix : null;

        String[] displayedValues = mNumberPickerMinute.getDisplayedValues();
        String[] minutes = null;
        if (displayedValues == null) {
            if (isShowDate()) {
                if (mSelectYear == mMaxYear && mSelectMonth == mMaxMonth && mSelectDay == mMaxDay && mSelectHour == mMaxHour && mMaxMinute != 59) {
                    //设置最大时间
                    minutes = DateTimeUtils.getDisplayMinutes(0, mMaxMinute, suffix);
                } else if (mSelectYear == mMinYear && mSelectMonth == mMinMonth && mSelectDay == mMinDay && mSelectHour == mMinHour && mMinMinute != 0) {
                    //设置最小时间
                    minutes = DateTimeUtils.getDisplayHours(mMinMinute, 59, suffix);
                } else {
                    minutes = DateTimeUtils.getDisplayHours(0, 59, suffix);
                }
            } else {
                if (mSelectHour == mMaxHour && mMaxMinute != 59) {
                    //设置最大时间
                    minutes = DateTimeUtils.getDisplayMinutes(0, mMaxMinute, suffix);
                } else if (mSelectHour == mMinHour && mMinMinute != 0) {
                    //设置最小时间
                    minutes = DateTimeUtils.getDisplayHours(mMinMinute, 59, suffix);
                } else {
                    minutes = DateTimeUtils.getDisplayHours(0, 59, suffix);
                }
            }

        } else {
            if (isShowDate()) {
                if (mSelectYear == mMaxYear && mSelectMonth == mMaxMonth && mSelectDay == mMaxDay && mSelectHour == mMaxHour && mMaxMinute != 59) {
                    //设置最大时间
                    minutes = DateTimeUtils.getDisplayMinutes(0, mMaxMinute, suffix);
                } else if (mSelectYear == mMinYear && mSelectMonth == mMinMonth && mSelectDay == mMinDay && mSelectHour == mMinHour && mMinMinute != 0) {
                    //设置最小时间
                    minutes = DateTimeUtils.getDisplayHours(mMinMinute, 59, suffix);
                } else {
                    if (displayedValues.length != 60) {
                        minutes = DateTimeUtils.getDisplayHours(0, 59, suffix);
                    }
                }
            } else {
                if (mSelectHour == mMaxHour && mMaxMinute != 59) {
                    //设置最大时间
                    minutes = DateTimeUtils.getDisplayMinutes(0, mMaxMinute, suffix);
                } else if (mSelectHour == mMinHour && mMinMinute != 0) {
                    //设置最小时间
                    minutes = DateTimeUtils.getDisplayHours(mMinMinute, 59, suffix);
                } else {
                    if (displayedValues.length != 60) {
                        minutes = DateTimeUtils.getDisplayHours(0, 59, suffix);
                    }
                }
            }

        }
        if (minutes != null) {
            if (DEBUG) {
                LogUtils.d(TAG, "刷新集合:分");
            }
            mNumberPickerMinute.setDisplayedValues(null);//
            mNumberPickerMinute.setMinValue(0);
            mNumberPickerMinute.setMaxValue(minutes.length - 1);
            mNumberPickerMinute.setDisplayedValues(minutes);
        }
        mSelectMinute = setSelect(mNumberPickerMinute, mSelectMinute);
    }

    /**
     * 设置NumberPicker的选择项
     *
     * @param numberPicker NumberPicker
     * @param select       需要选择的disPlay值
     * @return 真实选中的值, 如果select在最大值和最小值之间则为select, 否则为min
     */
    private int setSelect(NumberPicker numberPicker, int select) {
        String[] displayedValues = numberPicker.getDisplayedValues();
        int min = 0;
        int max = 0;
        if (mSuffixPosition == SUFFIX_POSITION_OUT) {
            min = Integer.parseInt(displayedValues[0]);
            max = Integer.parseInt(displayedValues[displayedValues.length - 1]);
        } else {
            min = getIntValue(displayedValues[0]);
            max = getIntValue(displayedValues[displayedValues.length - 1]);
        }
        if (DEBUG) {
            LogUtils.d(TAG, "setSelect:min=" + min + ",max=" + max + ",select=" + select);
        }
        if (select >= min && select <= max) {
            numberPicker.setValue(select - min);
        } else {
            select = min;
            numberPicker.setValue(0);
        }
        return select;
    }

    private int getIntValue(String value) {
        MATCHER_NUMBER.reset(value);
        if (MATCHER_NUMBER.find()) {
            return Integer.parseInt(MATCHER_NUMBER.group(0));
        }
        return 0;
    }

    @Override
    public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
        int id = picker.getId();
        if (id == R.id.date_numberPicker_year) {
            //年
            String[] years = picker.getDisplayedValues();
            String newYear = years[newVal];
            if (mSuffixPosition == SUFFIX_POSITION_OUT) {
                mSelectYear = Integer.parseInt(newYear);
            } else {
                mSelectYear = getIntValue(newYear);
            }
            if (DEBUG) {
//                LogUtils.d(TAG, "onValueChange:mSelectYear:" + mSelectYear);
            }
            refreshMonthOnChange();
            refreshDayOnChange();
            if (isShowTime()) {
                refreshHourOnChange();
                refreshMinuteOnChange();
            }

        } else if (id == R.id.date_numberPicker_month) {
            //月
            String[] months = picker.getDisplayedValues();
            String newMonth = months[newVal];
            if (mSuffixPosition == SUFFIX_POSITION_OUT) {
                mSelectMonth = Integer.parseInt(newMonth);
            } else {
                mSelectMonth = getIntValue(newMonth);
            }
            if (DEBUG) {
//                LogUtils.d(TAG, "onValueChange:mSelectMonth:" + mSelectMonth);
            }
            refreshDayOnChange();
            if (isShowTime()) {
                refreshHourOnChange();
                refreshMinuteOnChange();
            }
        } else if (id == R.id.date_numberPicker_day) {
            String[] days = picker.getDisplayedValues();
            String newDay = days[newVal];
            if (mSuffixPosition == SUFFIX_POSITION_OUT) {
                mSelectDay = Integer.parseInt(newDay);
            } else {
                mSelectDay = getIntValue(newDay);
            }
            if (DEBUG) {
//                LogUtils.d(TAG, "onValueChange:mSelectDay:" + mSelectDay);
            }
            if (isShowTime()) {
                refreshHourOnChange();
                refreshMinuteOnChange();
            }
        } else if (id == R.id.date_numberPicker_hour) {
            String[] hours = picker.getDisplayedValues();
            String newHour = hours[newVal];
            if (mSuffixPosition == SUFFIX_POSITION_OUT) {
                mSelectHour = Integer.parseInt(newHour);
            } else {
                mSelectHour = getIntValue(newHour);
            }
            if (DEBUG) {
//                LogUtils.d(TAG, "onValueChange:mSelectHour:" + mSelectHour);
            }
            refreshMinuteOnChange();
        } else if (id == R.id.date_numberPicker_minute) {
            String[] minutes = picker.getDisplayedValues();
            String newMinute = minutes[newVal];
            if (mSuffixPosition == SUFFIX_POSITION_OUT) {
                mSelectMinute = Integer.parseInt(newMinute);
            } else {
                mSelectMinute = getIntValue(newMinute);
            }
            if (DEBUG) {
//                LogUtils.d(TAG, "onValueChange:mSelectMinute:" + mSelectMinute);
            }
        }

        if (onSelectChangeListener != null) {
            onSelectChangeListener.onDateChange(mSelectYear, mSelectMonth, mSelectDay, mSelectHour, mSelectMinute);
            if (mDateFormat != null) {
                onSelectChangeListener.onDateChange(getDateOnChange());
            }

            /*int year = 0;
            int month = 0;
            int day = 0;
            int hour = 0;
            int minute = 0;
            if (isShowDate()) {
                year = mShowYear ? mSelectYear : 0;
                month = mShowMonth ? mSelectMonth : 0;
                day = mShowDay ? mSelectDay : 0;
            }
            if (isShowTime()) {
                hour = mShowHour ? mSelectHour : 0;
                minute = mShowMinute ? mSelectMinute : 0;
            }


            onSelectChangeListener.onDateChange(year, month, day, hour, minute);
            if (mDateFormat != null) {
                StringBuilder stringBuilder = new StringBuilder();
                boolean addSplit = false;
                if (year != 0) {
                    stringBuilder.append(year);
                    addSplit = true;
                }
                if (month != 0) {
                    if (addSplit) {
                        stringBuilder.append("-");
                    }
                    stringBuilder.append(TimeUtils.addZero(String.valueOf(month)));
                    addSplit = true;
                }
                if (day != 0) {
                    if (addSplit) {
                        stringBuilder.append("-");
                    }
                    stringBuilder.append(TimeUtils.addZero(String.valueOf(day)));
                    addSplit = true;
                }
                if (addSplit) {
                    stringBuilder.append(" ");
                }
                addSplit = false;
                if (hour != 0) {
                    stringBuilder.append(TimeUtils.addZero(String.valueOf(hour)));
                    addSplit = true;
                }
                if (minute != 0) {
                    if (addSplit) {
                        stringBuilder.append(":");
                    }
                    stringBuilder.append(TimeUtils.addZero(String.valueOf(minute)));
                }


                onSelectChangeListener.onDateChange(stringBuilder.toString());
            }*/
        }
    }

    /**
     * 当设置了onSelectChangeListener后用于生成格式化日期
     */
    private SimpleDateFormat cacheDateFormat;
    private Calendar cacheCalendar;
    private Date cacheDate;

    private String getDateOnChange() {
        if (cacheDateFormat == null) {
            cacheDateFormat = new SimpleDateFormat(mDateFormat, Locale.CANADA);
        }
        if (cacheCalendar == null) {
            cacheCalendar = Calendar.getInstance();
        }
        //必须使用，否则会继承自系统当前时间 /
        cacheCalendar.clear();
        if (isShowDate()) {
            cacheCalendar.set(Calendar.YEAR, mSelectYear);
            cacheCalendar.set(Calendar.MONTH, mSelectMonth - 1);
            cacheCalendar.set(Calendar.DAY_OF_MONTH, mSelectDay);
        }
        if (isShowTime()) {
            cacheCalendar.set(Calendar.HOUR_OF_DAY, mSelectHour);
            cacheCalendar.set(Calendar.MINUTE, mSelectMinute);
        }

        if (cacheDate == null) {
            cacheDate = new Date(cacheCalendar.getTimeInMillis());
        } else {
            cacheDate.setTime(cacheCalendar.getTimeInMillis());
        }
        return cacheDateFormat.format(cacheDate);
    }

    public Date getDate() {
        Calendar c = Calendar.getInstance();
        if (isShowDate()) {
            c.set(Calendar.YEAR, mSelectYear);
            c.set(Calendar.MONTH, mSelectMonth - 1);
            c.set(Calendar.DAY_OF_MONTH, mSelectDay);
        }
        if (isShowTime()) {
            c.set(Calendar.HOUR_OF_DAY, mSelectHour);
            c.set(Calendar.MINUTE, mSelectMinute);
        }
        return new Date(c.getTimeInMillis());
    }


    public String getDateString() {
        return getDateString(mDateFormat);
    }

    public String getDateString(String format) {
        if (format == null) {
            if (mMode == MODE_DATE) {
                format = DATE_FORMAT;
            } else if (mMode == MODE_TIME) {
                format = TIME_FORMAT;
            } else {
                format = DATE_TIME_FORMAT;
            }
        }
        Calendar c = Calendar.getInstance();
        if (isShowDate()) {
            c.set(Calendar.YEAR, mSelectYear);
            c.set(Calendar.MONTH, mSelectMonth - 1);
            c.set(Calendar.DAY_OF_MONTH, mSelectDay);
        }
        if (isShowTime()) {
            c.set(Calendar.HOUR_OF_DAY, mSelectHour);
            c.set(Calendar.MINUTE, mSelectMinute);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, Locale.CANADA);
        return simpleDateFormat.format(new Date(c.getTimeInMillis()));
    }

    /**
     * 设置mode 日期还是时间
     *
     * @param mode {@link #MODE_DATE}{@link #MODE_TIME}
     */
    public void setMode(int mode) {
        this.mMode = mode;
    }

    /**
     * 设置选中的年
     *
     * @param selectYear
     */
    public void setSelectYear(int selectYear) {
        this.mSelectYear = selectYear;
    }

    /**
     * 设置选中的月
     *
     * @param selectMonth
     */
    public void setSelectMonth(int selectMonth) {
        this.mSelectMonth = selectMonth;
    }

    /**
     * 设置选中的日
     *
     * @param selectDay
     */
    public void setSelectDay(int selectDay) {
        this.mSelectDay = selectDay;
    }

    /**
     * 设置选中的时
     *
     * @param selectHour
     */
    public void setSelectHour(int selectHour) {
        this.mSelectHour = selectHour;
    }

    /**
     * 设置选中的分
     *
     * @param selectMinute
     */
    public void setSelectMinute(int selectMinute) {
        this.mSelectMinute = selectMinute;
    }

    /**
     * 设置{@link #getDateString()}获取的日期数据格式
     *
     * @param dateFormat
     */
    public void setDateFormat(String dateFormat) {
        this.mDateFormat = dateFormat;
    }

    /**
     * 设置选中
     *
     * @param timeInMillis
     */
    public void setSelect(long timeInMillis) {
        if (timeInMillis > 0) {
            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(timeInMillis);
            mSelectYear = c.get(Calendar.YEAR);
            mSelectMonth = c.get(Calendar.MONTH) + 1;
            mSelectDay = c.get(Calendar.DAY_OF_MONTH);
            mSelectHour = c.get(Calendar.HOUR_OF_DAY);
            mSelectMinute = c.get(Calendar.MINUTE);
        }

    }

    /**
     * 设置最大可以选择的日期,必须先设置DateFormat
     *
     * @param select
     */
    public void setSelect(String select) {
        if (mDateFormat == null) {
            throw new IllegalArgumentException("必须先设置DateFormat");
        }
        if (select != null) {
            Date parse = TimeUtils.parse(select, mDateFormat);
            if (parse != null) {
                setSelect(parse.getTime());
            }
        }
    }


    /**
     * 设置最大可以选择的日期
     *
     * @param maxTimeInMillis
     */
    public void setMaxDate(long maxTimeInMillis) {
        if (maxTimeInMillis > 0) {
            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(maxTimeInMillis);
            mMaxYear = c.get(Calendar.YEAR);
            mMaxMonth = c.get(Calendar.MONTH) + 1;
            mMaxDay = c.get(Calendar.DAY_OF_MONTH);
            mMaxHour = c.get(Calendar.HOUR_OF_DAY);
            mMaxMinute = c.get(Calendar.MINUTE);
        } else {
            mMaxYear = DEF_MAX_YEAR;
            mMaxMonth = 12;
            mMaxDay = 31;
            mMaxHour = 23;
            mMaxMinute = 59;
        }
    }

    /**
     * 设置最大可以选择的日期,必须先设置DateFormat
     *
     * @param maxDate
     */
    public void setMaxDate(String maxDate) {
        if (mDateFormat == null) {
            throw new IllegalArgumentException("必须先设置DateFormat");
        }
        if (maxDate != null) {
            Date parse = TimeUtils.parse(maxDate, mDateFormat);
            if (parse != null) {
                setMaxDate(parse.getTime());
            }
        }
    }


    /**
     * 设置最小可以选择的日期
     *
     * @param minTimeInMillis
     */
    public void setMinDate(long minTimeInMillis) {
        if (minTimeInMillis > 0) {
            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(minTimeInMillis);
            mMinYear = c.get(Calendar.YEAR);
            mMinMonth = c.get(Calendar.MONTH) + 1;
            mMinDay = c.get(Calendar.DAY_OF_MONTH);
            mMinHour = c.get(Calendar.HOUR_OF_DAY);
            mMinMinute = c.get(Calendar.MINUTE);
        } else {
            mMinYear = DEF_MIN_YEAR;
            mMinMonth = 1;
            mMinDay = 1;
            mMinHour = 0;
            mMinMinute = 0;
        }
    }

    /**
     * 设置最小可以选择的日期,必须先设置DateFormat
     *
     * @param minDate
     */
    public void setMinDate(String minDate) {
        if (mDateFormat == null) {
            throw new IllegalArgumentException("必须先设置DateFormat");
        }
        if (minDate != null) {
            Date parse = TimeUtils.parse(minDate, mDateFormat);
            if (parse != null) {
                setMinDate(parse.getTime());
            }
        }
    }

    /**
     * 设置最小选择的年
     *
     * @param minYear
     */
    public void setMinYear(int minYear) {
        this.mMinYear = minYear;
    }

    /**
     * 设置最大选择的年
     *
     * @param maxYear
     */
    public void setMaxYear(int maxYear) {
        this.mMaxYear = maxYear;
    }

    /**
     * 设置最小选择的月
     *
     * @param minMonth
     */
    public void setMinMonth(int minMonth) {
        this.mMinMonth = minMonth;
    }

    /**
     * 设置最大选择的月
     *
     * @param maxMonth
     */
    public void setMaxMonth(int maxMonth) {
        this.mMaxMonth = maxMonth;
    }

    /**
     * 设置最小选择的日
     *
     * @param minDay
     */
    public void setMinDay(int minDay) {
        this.mMinDay = minDay;
    }

    /**
     * 设置最大选择的日
     *
     * @param maxDay
     */
    public void setMaxDay(int maxDay) {
        this.mMaxDay = maxDay;
    }

    /***
     * 设置最小选择的时
     * @param minHour
     */
    public void setMinHour(int minHour) {
        this.mMinHour = minHour;
    }

    /**
     * 设置最大选择的时
     *
     * @param maxHour
     */
    public void setMaxHour(int maxHour) {
        this.mMaxHour = maxHour;
    }

    /**
     * 设置最小选择的分
     *
     * @param minMinute
     */
    public void setMinMinute(int minMinute) {
        this.mMinMinute = minMinute;
    }

    /**
     * 设置最大选择的分
     *
     * @param maxMinute
     */
    public void setMaxMinute(int maxMinute) {
        this.mMaxMinute = maxMinute;
    }

    /**
     * 设置后缀的位置
     *
     * @param suffixPosition {@link #SUFFIX_POSITION_IN}{@link #SUFFIX_POSITION_OUT}
     */
    public void setSuffixPosition(int suffixPosition) {
        this.mSuffixPosition = suffixPosition;
        mNumberPickerHour.setDisplayedValues(null);
        mNumberPickerMinute.setDisplayedValues(null);
    }

    public void setDateSuffix(String yearSuffix, String monthSuffix, String daySuffix) {
        this.mYearSuffix = yearSuffix;
        this.mMonthSuffix = monthSuffix;
        this.mDaySuffix = daySuffix;
    }

    public void setTimeSuffix(String hourSuffix, String minuteSuffix) {
        this.mHourSuffix = hourSuffix;
        this.mMinuteSuffix = minuteSuffix;
    }


    public void setTextSize(float textSize) {
        mNumberPickerYear.setTextSize(textSize);
        mNumberPickerMonth.setTextSize(textSize);
        mNumberPickerDay.setTextSize(textSize);
        mNumberPickerHour.setTextSize(textSize);
        mNumberPickerMinute.setTextSize(textSize);
        mTvYearSuffix.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        mTvMonthSuffix.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        mTvDaySuffix.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        mTvHourSuffix.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        mTvMinuteSuffix.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
    }


    public void setTextColor(int textColor) {
        mNumberPickerYear.setTextColor(textColor);
        mNumberPickerMonth.setTextColor(textColor);
        mNumberPickerDay.setTextColor(textColor);
        mNumberPickerHour.setTextColor(textColor);
        mNumberPickerMinute.setTextColor(textColor);
        mTvYearSuffix.setTextColor(textColor);
        mTvMonthSuffix.setTextColor(textColor);
        mTvDaySuffix.setTextColor(textColor);
        mTvHourSuffix.setTextColor(textColor);
        mTvMinuteSuffix.setTextColor(textColor);
    }


    public void setSelectionDivider(Drawable divider) {
        mNumberPickerYear.setSelectionDivider(divider);
        mNumberPickerMonth.setSelectionDivider(divider);
        mNumberPickerDay.setSelectionDivider(divider);
        mNumberPickerHour.setSelectionDivider(divider);
        mNumberPickerMinute.setSelectionDivider(divider);
    }

    public void setSelectionDivider(int dividerColor) {
        mNumberPickerYear.setSelectionDivider(dividerColor);
        mNumberPickerMonth.setSelectionDivider(dividerColor);
        mNumberPickerDay.setSelectionDivider(dividerColor);
        mNumberPickerHour.setSelectionDivider(dividerColor);
        mNumberPickerMinute.setSelectionDivider(dividerColor);
    }

    public void setSelectionDividerHeight(int dividerHeight) {
        mNumberPickerYear.setSelectionDividerHeight(dividerHeight);
        mNumberPickerMonth.setSelectionDividerHeight(dividerHeight);
        mNumberPickerDay.setSelectionDividerHeight(dividerHeight);
        mNumberPickerHour.setSelectionDividerHeight(dividerHeight);
        mNumberPickerMinute.setSelectionDividerHeight(dividerHeight);
    }


    public void setOnSelectChangeListener(OnSelectChangeListener onSelectChangeListener) {
        this.onSelectChangeListener = onSelectChangeListener;
    }

    /**
     * 属性改变后刷新
     */
    public void notifyDataChange() {
        initDate();
    }

    /**
     * 选择监听器,手动选择是回掉
     */
    public interface OnSelectChangeListener {
        void onDateChange(int year, int month, int day, int hour, int minute);

        /**
         * 设置了dateFormat后才会回掉
         *
         * @param date
         */
        void onDateChange(String date);
    }

}
